package com.wl.dzt.sys.core.dao.tree;

import com.wl.dzt.sys.core.dao.DB;
import com.wl.dzt.sys.util.FieldUtil;
import com.wl.dzt.sys.util.LogicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.cglib.beans.BeanMap;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


/**
 * @author wl_code@163.com
 * @version 1.0
 * @date 2018/7/5/005
 * @description 树形数据构建者
 * 用于提供支持构建树形结构数据的静态函数
 */
public class TreeBuilder {
    private static final Logger log = LoggerFactory.getLogger(TreeBuilder.class);


    private TreeBuilder() {
    }

    /**
     * <b>关键节点数据适配器</b>
     * <p>
     * 表达式写法:id,name,pid,age,gender<br>
     * 编号字段,文本字段,上级节点字段,扩展字段<br>
     * 其中上级节点字段为 * 则表示无视层级关系
     * </p>
     */
    public static TreeMapper createRelationMapper(TreeSetting setting) {
        TreeMapper mapper = (entity) -> {
            TreeNode node = new TreeNode();
            BeanMap beanMap = BeanMap.create(entity);
            node.setId(beanMap.get(setting.getIdField()).toString());
            node.setText(LogicUtil.thenNull(beanMap.get(setting.getTextField()), null));
            if (!"*".equalsIgnoreCase(setting.getParentIdField())) {
                node.setParentId(
                        LogicUtil.thenNull(FieldUtil.getFieldValueByCascade(setting.getParentIdField(), entity), null));
            }
            if (setting.getExpanFields() != null) {
                Arrays.stream(setting.getExpanFields()).forEach((expan) -> node.getExpansions().put(expan, FieldUtil.getFieldValueByCascade(expan, entity)));
            }
            return node;
        };
        return mapper;
    }

    /**
     * 级联获取树形结构
     * 根据所传递的数据集合,在其中遍历构建树形结构数据.
     *
     * @param data
     * @param setting
     * @return
     */
    public static List<Map<String, Object>> cascadeTree(List<?> data, TreeSetting setting) {
        List<Map<String, Object>> info = cascadeTrees(data, setting);
        if (setting.isContainOneself() && !data.isEmpty()) {
            Class<?> clazz = data.get(0).getClass();
            Object obj = DB.get(clazz, setting.getStartId(), setting.getFields());
            TreeNode node = setting.getMapper().mapper(obj);
            node.setChildrens(info);
            node.setLeaf(false);
            List<Map<String, Object>> treeData = new ArrayList<Map<String, Object>>();
            treeData.add(node.toMap());
            return treeData;
        }
        return info;
    }

    private static List<Map<String, Object>> cascadeTrees(List<?> data, TreeSetting setting) {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        String startId = setting.getStartId();
        boolean notHierarchy = setting.getParentIdField().equals("*");
        for (int i = 0; i < data.size(); i++) {
            Object entity = data.get(i);
            TreeNode node = setting.getMapper().mapper(entity);
            // 上级id等于当前id的时候则认为是子节点
            // 或者上级id属性为*则表示无视层次结构关系
            if (startId.equalsIgnoreCase(node.getParentId()) || notHierarchy) {
                // 不为异步并且存在上下级关系的时候的时候递归加载下级节点
                if ((!setting.isAsync()) && !notHierarchy) {
                    TreeSetting nextSeeting = new TreeSetting();
                    BeanUtils.copyProperties(setting, nextSeeting);
                    nextSeeting.setStartId(node.getId());
                    node.setChildrens(cascadeTrees(data, nextSeeting));
                    node.setLeaf(node.getChildrens().isEmpty());
                }
                list.add(node.toMap());
            }
        }
        return list;
    }

}
